﻿package javase.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadDemo {

	public static void main(String[] args) {
		Thread threadone = new Threadone();
		Thread threadtwo = new Thread(new Threadtwo());
		threadone.start();
		try {
			Thread.sleep(3500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		threadtwo.start();
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		Thread threadthree = new Thread(new Threadthree());
		Thread threadfour = new Thread(new Threadfour());
		threadthree.start();
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		threadfour.start();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		Thread threadsubtractor = new Thread(new Subtractor());
		Thread threadadder = new Thread(new Adder());
		threadsubtractor.start();
		threadadder.start();
	}
}

// 线程实现方法一：继承Thread类
class Threadone extends Thread {
	int i = 0;

	public void run() {
		System.out.println("enter threadone...");
		while (i != -3) {
			i--;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("i=" + i);
		}
		System.out.println("threadone is being over");
	}
}

// 线程实现方法二：实现Runnable接口
class Threadtwo implements Runnable {
	int i = 0;

	@Override
	public void run() {
		System.out.println("enter threadtwo...");
		while (i != 3) {
			i++;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("i=" + i);
		}
		System.out.println("threadtwo is being over");
	}
}

class Threadthree implements Runnable {
	public void run() {
		/*
		 * 由于这里的Threadthree和下面的Threadfour内部run方法要用同一对象作为监视器，
		 * 我们这里不能用this，因为在Threadfour里面的this和这个Threadthree的this不是同一个对象。
		 * 我们用ThreadDemo.class这个字节码对象，当前虚拟机里引用这个变量时， 指向的都是同一个对象。
		 */
		synchronized (ThreadDemo.class) {
			System.out.println("enter threadthree...");
			System.out.println("threadthree is waiting");
			try {
				/*
				 * 释放锁有两种方式， 第一种方式是程序自然离开监视器的范围， 也就是离开了synchronized关键字管辖的代码范围，
				 * 另一种方式就是在synchronized关键字管辖的代码内部调用监视器对象的wait方法。 这里，使用wait方法释放锁。
				 */
				ThreadDemo.class.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("threadthree is going on...");
			System.out.println("threadthree is being over!");
		}
	}
}

class Threadfour implements Runnable {
	public void run() {
		synchronized (ThreadDemo.class) {
			System.out.println("enter threadfour...");
			System.out.println("threadfour notify other thread can release wait status..");
			/*
			 * 由于notify方法并不释放锁， 即使thread2调用下面的sleep方法休息了1秒， 但thread1仍然不会执行，
			 * 因为thread2没有释放锁， 所以Thread1无法得到锁。
			 */
			ThreadDemo.class.notify();
			System.out.println("threadfour is sleeping one second...");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("threadfour is going on...");
			System.out.println("threadfour is being over!");
		}
	}
}
//Lock
class Subtractor implements Runnable {
	private Lock lock = new ReentrantLock();
	private int j = 0;

	public void run() {
		while (j!=-3) {
			lock.lock();
			try {
				System.out.println("j--=" + j--);
			} finally {
				lock.unlock();
			}
		}
	}
}

class Adder implements Runnable {
	private Lock lock = new ReentrantLock();
	private int j = 0;

	public void run() {
		while (j!=3) {
			lock.lock();
			try {
				System.out.println("j++=" + j++);
			} finally {
				lock.unlock();
			}
		}
	}
}
/*
 * package javatest.test;

//题目：线程1执行2次，线程2执行3次，线程1在执行2次，线程2再执行3次，这样循环3次 
public class ThreadTest {

	public static void main(String[] args) {
		new ThreadTest().init();
	}

	public void init() {
		final X x = new X();
		new Thread(new Runnable() {
			public void run() {
				for (int i = 0; i < 3; i++) {
					x.threadone();
				}
			}
		}).start();
		new Thread(new Runnable() {
			public void run() {
				for (int i = 0; i < 3; i++) {
					x.threadtwo();
				}
			}
		}).start();

	}

	class X {
		boolean flag = true;
		int countone = 0;
		int counttwo = 0;

		public synchronized void threadone() {
			countone++;
			if (flag) {
				try {
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			for (int i = 0; i < 2; i++) {
				System.out.println(Thread.currentThread().getName());
			}
			this.notify();
			flag = true;
			System.out.println("threadone is runing the "+countone+" time");
		}

		public synchronized void threadtwo() {
			counttwo++;
			if (!flag) {
				try {
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			for (int i = 0; i < 3; i++) {
				System.out.println(Thread.currentThread().getName());
			}
			this.notify();
			flag = false;
			System.out.println("threadtwo is runing the "+countone+" time");
		}
	}
}
 * */
